#ifndef SANDBOX_FILE
#define SANDBOX_FILE
#include "basic.h"
#include <vector>
#include<fstream>
#include <iostream>
#include <ctime>
/*
 * SandBox Executable file header:
 * byte 0~7:sandbox\x20
 * byte 8~16:Entry address
 * byte 16~19:Count of segments
 * byte 20~23:File size
 * byte 32~:Segment table
 */
enum PTYPE
{
	CODE,
	DATA,
	STACK,
	TABLE
};
struct program_table
{
	// size:16byte
	word type;
	word size;
	dword begin;
	qword entry;
	void swap()
	{
		this->type = swapEndian(this->type);
		this->size = swapEndian(this->size);
		this->begin = swapEndian(this->begin);
		this->entry = swapEndian(this->entry);
	}
};
static std::vector<program_table> tables;
static dword p_offset;
const char std_magic[8] = {'s', 'a', 'n', 'd', 'b', 'o', 'x', '\x20'};
void checkHeader(const char *filename)
{
	std::ifstream inFile(filename);
	char magic[8];
	inFile.read(magic, 8);
	for (int i = 0; i < 8; i++)
	{
		if (magic[i] != std_magic[i])
		{
			std::cout << "Check your file type!!!\n";
			exit(0);
		}
	}
	inFile.close();
}
void getHeader(const char *filename)
{
	std::ifstream inFile(filename);
	inFile.seekg(8);
	program_table temp = {0, 0, 0, 0};
	dword count = 0;
	inFile.read((char *)&p_offset, sizeof(qword));
	inFile.read((char *)&count, sizeof(dword));
	count = swapEndian(count);
	p_offset = swapEndian(p_offset);
	inFile.seekg(0x20);
	for (dword i = 0; i < count; i++)
	{
		inFile.read((char *)(&temp), 16);
		temp.swap();
		tables.push_back(temp);
	}
	inFile.close();
}
void loadImage(const char *filename)
{
	std::ifstream inFile(filename);
	qword base = 0;
	for (auto &i : tables)
	{
		base = 0;
		inFile.seekg(i.begin,std::ios::beg);
		base = i.entry + p_offset;
		byte temp = 0;
		switch (i.type & 0x03)
		{
		case CODE:
			base += addr_regs[Code];
			for (int n = 0; n < i.size; n++)
				ram[base + n] = inFile.get();
			break;
		case DATA:
			base += addr_regs[Data];
			for (int n = 0; n < i.size; n++)
				ram[base + n] = inFile.get();
			break;
		case STACK:
			base += addr_regs[Stack];
			for (int n = 0; n < i.size; n++)
				ram[base - n] = inFile.get();
			break;
		}
	}
	inFile.close();
}
#endif